<?php
/*
*    Author : lemonice
*
*    Email:chengciming@126.com
*    
*    时间：2011-08
*
*    说明：验证码图片类
*
*    操作：直接实例化类即可输出验证码，有两种类型，一种是有背景图（需要有图片提供），另一种是无背景图片（即白色背景）
*	 示例：$code = new yzcode();  可以传入参数设置大小和属性之类，详细可以看下面
*
*/
/*
检查验证码是否正确的方法
$yzcode = new yzcode();
$yzcode->session_word = 'yzcode';  //这里是定义的session字段名称，默认是yzcode
if (!$yzcode->check_word($_REQUEST['yzcode']))
{
	echo '您输入的验证码不正确！';
}*/

class yzcode
{
    /**
     * 背景图片所在目录
     *
     * @var string  $folder
     */
    var $folder     = '';  //如果$folder等于空则无背景验证码，需要有背景验证码则此值填写验证码背景图片的路径（目录），如：'../load/images/'

    /**
     * 背景图片的文件类型，输出的图片也一致！
     *
     * @var string  $img_type
     */
    var $img_type   = 'png';   //目前只支持三种,gif/png/jpg
	
	
	/**
     * 想要显示什么文字的验证码，1为纯数字，2为数字加小写字母，3为数字加大写字母，4为纯小写字母，5为小写字母加大写字母，6为纯大写字母，7为数字加小写字母加大写字母
     *
     * @var int  $type
     */
    var $type   = 1;
	
	
	/**
     * 想要显示多少位文字
     *
     * @var int  $type
     */
    var $number   = 4;
	
	
    /*------------------------------------------------------ */
    //-- 存在session中的名称
    /*------------------------------------------------------ */
    var $session_word = 'yzcode';

    /**
     * 背景图片以及背景颜色()
     *
     * 0 => 背景图片的文件名
     * 1 => Red, 2 => Green, 3 => Blue    后面三个数是显示这张图片的时候文字的颜色
     * @var array   $themes
     */
    var $themes_jpg = array(
        1 => array('code.png', 255, 25, 50),
        2 => array('code.png', 0, 0, 0),
        3 => array('code.png', 0, 0, 0),
        4 => array('code.png', 255, 255, 255),
        5 => array('code.png', 255, 255, 255),
    );

    var $themes_gif = array(
        1 => array('code.png', 255, 255, 255),
        2 => array('code.png', 0, 0, 0),
        3 => array('code.png', 0, 0, 0),
        4 => array('code.png', 255, 255, 255),
        5 => array('code.png', 255, 255, 255),
    );
	
	var $themes_png = array(
        1 => array('code.png', 255, 255, 255),
        2 => array('code.png', 0, 0, 0),
        3 => array('code.png', 0, 0, 0),
        4 => array('code.png', 255, 255, 255),
        5 => array('code.png', 255, 255, 255),
    );

    /**
     * 图片的宽度
     *
     * @var integer $width
     */
    var $width      = 88;

    /**
     * 图片的高度
     *
     * @var integer $height
     */
    var $height     = 40;

    /**
     * 构造函数
     *
     * @access  public
     * @param   string  $folder     背景图片所在目录
     * @param   integer $width      图片宽度
     * @param   integer $height     图片高度
     * @return  bool
     */
    function yzcode($folder = '', $width = 88, $height = 40, $number = 4, $type = 1)
    {
        if (!empty($folder))
        {
            $this->folder = $folder;
        }
		
		$this->number    = $number ? $number : 4;
		$this->type    = $type ? $type : 3;
        $this->width    = $width ? $width : 88;
        $this->height   = $height ? $height : 40;

        /* 检查是否支持 GD */
        if (PHP_VERSION >= '4.3')
        {

            function_exists('imagecreatetruecolor') or function_exists('imagecreate');
        }else
        {

            ((imagetypes() & IMG_GIF) > 0) or ((imagetypes() & IMG_JPG)) > 0 ;
        }
		
		if(empty($folder))
		{
			
			$this->make_no_bgimage();
		}else
		{
			$this->make_bgimage();
		}
    }

    /**
     * 构造函数
     *
     * @access  public
     * @param
     *
     * @return void
     */
    function __construct($folder = '', $width = 88, $height = 30, $number = 4, $type = 1)
    {
        $this->yzcode($folder, $width, $height, $number, $type);
    }


    /**
     * 检查给出的验证码是否和session中的一致
     *
     * @access  public
     * @param   string  $word   验证码
     * @return  bool
     */
    function check_word($word)
    {
        $recorded = isset($_SESSION[$this->session_word]) ? base64_decode($_SESSION[$this->session_word]) : '';
        $given    = $this->encrypts_word(strtoupper($word));

        return (preg_match("/$given/", $recorded));
    }

    /**
     * 生成有背景图片的验证码
     *
     * @access  public
     * @param   string  $word   验证码
     * @return  mix
     */
    function make_bgimage()
    {
        $word = $this->generate_word();
		

        /* 记录验证码到session */
        $this->record_word($word);

        /* 验证码长度 */
        $letters = strlen($word);

        /* 选择一个随机的方案 */
        mt_srand((double) microtime() * 1000000);

        if ($this->img_type == 'gif')
        {
            $theme  = $this->themes_gif[mt_rand(1, count($this->themes_gif))];
        }elseif($this->img_type == 'png')
		{
			$theme  = $this->themes_png[mt_rand(1, count($this->themes_png))];
		}else
        {
            $theme  = $this->themes_jpg[mt_rand(1, count($this->themes_jpg))];
        }

        if (!file_exists($this->folder . $theme[0]))
        {
            return false;
        }
        else
        {
			if($this->img_type == 'png')
			{
				$img_bg    = imagecreatefrompng($this->folder . $theme[0]);
			}elseif($this->img_type == 'gif')
			{
				$img_bg    = imagecreatefromgif($this->folder . $theme[0]);
			}else
			{
				$img_bg    = imagecreatefromjpeg($this->folder . $theme[0]);
			}
            
            $bg_width  = imagesx($img_bg);
            $bg_height = imagesy($img_bg);

            $img_org   = ((function_exists('imagecreatetruecolor')) && PHP_VERSION >= '4.3') ?
                          imagecreatetruecolor($this->width, $this->height) : imagecreate($this->width, $this->height);

            /* 将背景图象复制原始图象并调整大小 */
            if (function_exists('imagecopyresampled') && PHP_VERSION >= '4.3') // GD 2.x
            {
                imagecopyresampled($img_org, $img_bg, 0, 0, 0, 0, $this->width, $this->height, $bg_width, $bg_height);
            }
            else // GD 1.x
            {
                imagecopyresized($img_org, $img_bg, 0, 0, 0, 0, $this->width, $this->height, $bg_width, $bg_height);
            }
            imagedestroy($img_bg);

            $clr = imagecolorallocate($img_org, $theme[1], $theme[2], $theme[3]);

            /* 绘制边框 */
            //imagerectangle($img_org, 0, 0, $this->width - 1, $this->height - 1, $clr);

            /* 获得验证码的高度和宽度 */
            $x = ($this->width - (imagefontwidth(5) * $letters)) / 2;
            $y = ($this->height - imagefontheight(5)) / 2;
            imagestring($img_org, 5, $x, $y, $word, $clr);

            header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');

            // HTTP/1.1
            header('Cache-Control: private, no-store, no-cache, must-revalidate');
            header('Cache-Control: post-check=0, pre-check=0, max-age=0', false);

            // HTTP/1.0
            header('Pragma: no-cache');
            if ($this->img_type == 'jpeg' && function_exists('imagecreatefromjpeg'))
            {
                header('Content-type: image/jpeg');
                imageinterlace($img_org, 1);
                imagejpeg($img_org, false, 95);
            }elseif($this->img_type == 'gif' && function_exists('imagecreatefromgif'))
			{
				header('Content-type: image/gif');
                imagegif($img_org);
			}else
            {
                header('Content-type: image/png');
                imagepng($img_org);
            }

            imagedestroy($img_org);

            return true;
        }
    }

    /*------------------------------------------------------ */
    //-- PRIVATE METHODs
    /*------------------------------------------------------ */

    /**
     * 对需要记录的串进行加密
     *
     * @access  private
     * @param   string  $word   原始字符串
     * @return  string
     */
    function encrypts_word($word)
    {
        return substr(md5($word), 1, 10);
    }

    /**
     * 将验证码保存到session
     *
     * @access  private
     * @param   string  $word   原始字符串
     * @return  void
     */
    function record_word($word)
    {
        $_SESSION[$this->session_word] = base64_encode($this->encrypts_word($word));
    }

    /**
     * 生成随机的验证码
     *
     * @access  private
     * @param   integer $length     验证码长度
     * @return  string
     */
    function generate_word()
    {
		$length = $this->number;
        $chars = $this->get_type_word();

        for ($i = 0, $count = strlen($chars); $i < $count; $i++)
        {
            $arr[$i] = $chars[$i];
        }

        mt_srand((double) microtime() * 1000000);
        shuffle($arr);

        return substr(implode('', $arr), 5, $length);
    }
	
	/**
     * 生成无背景图片的验证码图片
     *
     * @access  private
     * @number  int     验证码长度
     * @return  string
     */
	function make_no_bgimage()
	{
		$string = $this->session_word;    //生成验证码后会设置一个session值，并且是MD5加密的，这个是定义验证码session值的字段名称
		$x_size = $this->width;    //生成的验证码图片的高
		$y_size = $this->height;   //生成的验证码图片的宽
		$number = $this->number;   //显示多少位验证码，默认为显示4位数
		$type = $this->type;   //验证码的类型：1为纯数字，2为数字加小写字母，3为数字加大写字母，4为纯小写字母，5为小写字母加大写字母，6为纯大写字母，7为数字加小写字母加大写字母
		
		$aimg = imagecreate($x_size,$y_size);
		$back = imagecolorallocate($aimg, 255, 255, 255);   //验证码图片的背景颜色
		$border = imagecolorallocate($aimg, 0, 0, 0);     //验证码图片的边框的颜色
		imagefilledrectangle($aimg, 0, 0, $x_size - 1, $y_size - 1, $back);
		$txt = $this->get_type_word();
		
		
		$txtlen=strlen($txt);
	
		$thetxt="";
		for($i=0;$i<$number;$i++)
		{
			$randnum=mt_rand(0,$txtlen-1);
			$randang=mt_rand(-10,10);	//文字旋转角度
			$rndtxt=substr($txt,$randnum,1);
			$thetxt.=$rndtxt;
			$rndx=mt_rand(1,5);
			$rndy=mt_rand(1,4);
			$colornum1=($rndx*$rndx*$randnum)%255;
			$colornum2=($rndy*$rndy*$randnum)%255;
			$colornum3=($rndx*$rndy*$randnum)%255;
			$newcolor=imagecolorallocate($aimg, $colornum1, $colornum2, $colornum3);
			imageString($aimg,3,$rndx+$i*21,5+$rndy,$rndtxt,$newcolor);
		}
		

		/* 记录验证码到session */
		$chars = $txt;
        for ($i = 0, $count = strlen($chars); $i < $count; $i++)
        {
            $arr[$i] = $chars[$i];
        }
        mt_srand((double) microtime() * 1000000);
        shuffle($arr);
        $this->record_word(substr(implode('', $arr), 5, $number));

		unset($txt);
		imagerectangle($aimg, 0, 0, $x_size - 1, $y_size - 1, $border);
		$newcolor="";
		$newx="";
		$newy="";
		$pxsum=40;	//干扰像素个数
		for($i=0;$i<$pxsum;$i++)
		{
			$newcolor=imagecolorallocate($aimg, mt_rand(0,254), mt_rand(0,254), mt_rand(0,254));
			imagesetpixel($aimg,mt_rand(0,$x_size-1),mt_rand(0,$y_size-1),$newcolor);
		}
		header("Pragma:no-cache");
		header("Cache-control:no-cache");
		header("Content-type: image/png");
		imagepng($aimg);
		imagedestroy($aimg);
		exit;
	}
	
	/**
     * 判断想要生成的验证码类型，即显示什么文字
     *
     * @access  private
     * @type    int     类型   //验证码的类型：1为纯数字，2为数字加小写字母，3为数字加大写字母，4为纯小写字母，5为小写字母加大写字母，6为纯大写字母，7为数字加小写字母加大写字母
     * @return  string
     */
    function get_type_word()
    {
		$type = $this->type;
        $number_txt = "23456789";
		$lowercase_txt = 'qwertyuiopasdfghjklzxcvbnm';
		$majuscule_txt = 'QWERTYUIOPASDFGHJKLZXCVBNM';
		if($type == 1)
		{
			$txt = '0123456789';
		}elseif($type == 2)
		{
			$txt = $number_txt.$lowercase_txt;
		}elseif($type == 3)
		{
			$txt = $number_txt.$majuscule_txt;
		}elseif($type == 4)
		{
			$txt = $lowercase_txt;
		}elseif($type == 5)
		{
			$txt = $lowercase_txt.$majuscule_txt;
		}elseif($type == 6)
		{
			$txt = $majuscule_txt;
		}elseif($type == 7)
		{
			$txt = $number_txt.$lowercase_txt.$majuscule_txt;
		}else
		{
			$txt = '0123456789';
		}
		return $txt;
    }
}

?>